﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Topping.Core.Logic;
using Topping.Core.Logic.Threads;
using TopMachine.Topping.Dto;
using TopMachine.Topping.Common.Structures;
using Topping.Core.Data.Db4o ;
using Topping.Core.Proxy.Local.Client;

namespace Topping.Core.Proxy.Local
{
    internal class Proxy : IProxy, IDisposable
    {
        #region Properties
        public string UserName { get; set; }


        #endregion

        private Proxy()
        {
        }

        #region Singleton
        private static volatile Proxy instance;
        private static object syncRoot = new Object();

        public static Proxy Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new Proxy();
                    }
                }

                return instance;
            }

        }
        #endregion

        #region ServerState
        GameServerState gameServerState = null;
        public GameServerState GetServerState()
        {
            if (gameServerState == null)
            {
                gameServerState = GameServerState.Instance;
            }
            return gameServerState;
        }


        #endregion


        public bool CheckVersion(string version)
        {
            return true;
        }

        #region Chatting

        public void ActivateChat()
        {
            this.GetServerState().Players[UserName].ChatActivated = true;
        }




        public void DeactivateChat()
        {
            this.GetServerState().Players[UserName].ChatActivated = false;
        }


        public void SendMessage(MessageDto m)
        {
            MessageProcessor.Instance.AddMessage(m);
        }


        public List<MessageDto> GetMessages()
        {
            if (UserName != null)
            {
                Player p = this.GetServerState().Players[UserName];
                MessageProxy.Proxy.QueueMessages(p.GetMessages());
            }

            return null;

        }
        #endregion

        #region Login

        public List<UserDto> GetUsers()
        {
            throw new NotImplementedException();
        }
        public bool ChangedPwdUser(UserDto us, string NewPwd)
        {
            throw new NotImplementedException();
        }
       
        public bool UpdateUser(UserDto us)
        {
            throw new NotImplementedException();
        }

        public bool DeleteUser(UserDto us)
        {
            throw new NotImplementedException();
        }
       

        public Guid Login(string userName, string passWord, int version)
        {
            Guid g = Guid.Empty;
            UserName = userName.ToLower();
            ToppingAccessor ta = new ToppingAccessor();
                if (ta.Login(UserName, passWord))
                {
                    ta.Dispose(); 
                    g = this.GetServerState().AddPlayer(UserName);

                    MessageDto m = new MessageDto();
                    m.From = UserName;
                    m.MessageType = MessageType.Login;
                    SendMessage(m);
                }

            return g;
        }

        public void Logoff()
        {
            MessageDto m = new MessageDto();
            m.From = UserName;
            m.MessageType = MessageType.Logoff;
            SendMessage(m);
        }

        #endregion

        #region ROOMS

        public void SendMessageToRoom(int x, MessageDto m)
        {
            RoomMessageProcessor.Instance.AddMessage(m);
        }

        public RoomDto GetRoom(int roomId)
        {
            return this.GetServerState().getRoom(roomId);
        }

        public List<Room> GetRooms()
        {
            return this.GetServerState().Rooms;
        }
        public List<RoomDto> GetRoomsDto()
        {
            return (from c in this.GetServerState().Rooms select (RoomDto)c).ToList();
        }
        #endregion

        #region Room
        private void SendRoomMessage(Room r, MessageDto m)
        {
            RoomMessageProcessor.Instance.AddMessage(m);
        }

        public void ResetRooms()
        {
            this.GetServerState().ResetRooms();
        }

        public RoomDto InitRoom(Room room, bool generate)
        {
            RoomDto r = this.GetServerState().CreateRoom(room, generate, UserName);

            MessageDto m = new MessageDto();
            m.From = "System";
            m.MessageType = MessageType.RoomCreate;
            m.Room = r;
            m.Text = UserName;
            SendRoomMessage(room, m);


            return r;
        }


        public RoomDto JoinRoom(int roomId)
        {
            Room r = this.GetServerState().Rooms[roomId];
            //  r.JoinRoom(UserName, false);

            MessageDto m = new MessageDto();
            m.From = "System";
            m.MessageType = MessageType.RoomEnter;
            m.Text = UserName;
            SendRoomMessage(r, m);

            return r.GetDto();
        }

        public void LeaveAnyRoom()
        {
            Player p = this.GetServerState().Players[UserName];
            if (p.CurrentRoom >= 0)
            {
                Room r = this.GetServerState().Rooms[p.CurrentRoom];
                r.LeaveRoom(p.Pseudo);
                p.CurrentRoom = -1;
                MessageDto m = new MessageDto();
                m.From = UserName;
                m.MessageType = MessageType.RoomLeave;
                m.Room = r.GetDto();
                m.Text = UserName;
                SendRoomMessage(r, m);
            }
        }

        public RoomDto LeaveRoom()
        {
            Room r = this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom];
            r.FinishGame(UserName);
            r.LeaveRoom(UserName);
            this.GetServerState().Players[UserName].CurrentRoom = -1;

            MessageDto m = new MessageDto();
            m.From = UserName;
            m.MessageType = MessageType.RoomLeave;
            m.Text = UserName;
            m.Room = r.GetDto();
            SendRoomMessage(r, m);

            return r.GetDto();
        }

        public string[] ListRoomPlayers(int roomid)
        {
            Room r = this.GetServerState().Rooms[roomid];
            return r.GetPlayers().ToArray();
        }

        public string[] ListRoomActivePlayers(int roomid)
        {
            Room r = this.GetServerState().Rooms[roomid];
            return r.GetActivePlayers().ToArray();
        }

        #endregion

        #region Game
        public GeneratedGameDto GetGame()
        {
            return this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom].GetGeneratedGame();
        }

        public void SetGame(GeneratedGameDto game)
        {

            Room r = this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom];
            if (r.GetGeneratedGame() == null)
            {
                r.SetGeneratedGame(game);
                r.GameStatus = RoomStatus.Created;

                MessageDto m = new MessageDto();
                m.From = "System";
                m.MessageType = MessageType.RoomStatusChange;
                m.Text = "La partie est générée";
                m.ToRoom = r.RoomId;
                m.Room = r.GetDto();
                SendMessage(m);
            }
        }

        public void GetListPlayedRound(string playerSearch)
        {
            // no defined
        }


        public void AddPlayedRound(PlayerSummaryDto summary, PlayedGameRoundDto pgr)
        {
            Room r = this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom];
            // Room r = this.GetServerState().Rooms[roomId];
            r.AddPlayedRound(UserName, summary, pgr);

            MessageDto m = new MessageDto();
            m.From = "System";
            m.MessageType = MessageType.GameSummaryUpdated;
            m.Text = UserName;
            m.XmlObjectType = summary.GetType().FullName;
            m.XmlObject = new TopMachine.Desktop.Overall.ObjectSerializer<PlayerSummaryDto>().Serialize(summary);
            m.Room = r.GetDto();
            m.Room.Configuration = null;
            SendRoomMessage(r, m);

            m = new MessageDto();
            m.From = "System";
            m.MessageType = MessageType.GameSummaryRoundUpdated ;
            m.Text = UserName;
            m.XmlObjectType = pgr.GetType().FullName;
            m.XmlObject = new TopMachine.Desktop.Overall.ObjectSerializer<PlayedGameRoundDto>().Serialize(pgr);
            m.Room = r.GetDto();
            m.ToRoom = r.RoomId ;
            SendRoomMessage(r, m);
        }

        public void FinishGame()
        {
            Room r = this.GetServerState().Rooms[0];
            r.FinishGame(UserName);
        }

        public void StartGame()
        {
            Room r = this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom];
            r.StartGame(UserName);
        }

        public List<GamesDetailDto> GetGamesDetail(string player, int year, int mont, Guid configId)
        {
            using (ToppingAccessor ta = new ToppingAccessor())
            {
                return ta.GetGamesDetail(player, year, mont, configId);
            }
        }

        public FinalRoomDto  GetFinalRoom(int RoomId) 
        {
            Room r = this.GetServerState().Rooms[this.GetServerState().Players[UserName].CurrentRoom];
           return r.finalRoomDto;

        }


        #endregion

        #region Configuration
        public List<ConfigGameDto> GetConfigurations()
        {
            using (ToppingAccessor ta = new ToppingAccessor())
            {
                return ta.GetConfigurations();
            }
        }

        public bool UpdateConfiguration(ConfigGameDto cfg)
        {
            using (ToppingAccessor ta = new ToppingAccessor())
            {
                return ta.UpdateConfiguration(cfg);
            }
        }

        public bool DeleteConfiguration(ConfigGameDto cfg)
        {
            using (ToppingAccessor ta = new ToppingAccessor())
            {
                return ta.DeleteConfiguration(cfg);
            }
        }

        public List<RankingDto> GetRankings(string player, int year, int mont, Guid ConfigId)
        {
            using (ToppingAccessor ta = new ToppingAccessor())
            {
                return ta.GetRankings(player, year, mont, ConfigId);
            }
        }
        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (RoomMessageProcessor.Instance != null)
            { RoomMessageProcessor.Instance.StopService(); }

            if (MessageProcessor.Instance != null)
            {
                MessageProcessor.Instance.StopService();
            }
        }

        #endregion

        #region IProxy Members




        #endregion

        #region IProxy Members




        #endregion

        public string[] ListPlayers()
        {

            List<string> lstPlayers = this.GetServerState().Pseudos;
            if (lstPlayers != null) return lstPlayers.ToArray();
            return null;
        }
               


        #region IProxy Members

        public bool DeleteGameXML(string fn)
        {
            throw new NotImplementedException();
        }

        #endregion

     
    }
}
